package com.qf.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qf.common.PageParam;
import com.qf.common.PageVO;
import com.qf.common.UserUtils;
import com.qf.entity.Clock;
import com.qf.entity.User;
import com.qf.exception.CustomerException;
import com.qf.mapper.ClockMapper;
import com.qf.service.ClockService;
import com.qf.service.UserService;
import com.qf.vo.ClockStatsVO;
import com.qf.vo.UserClockVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author zdl
 * @date 2025/4/14
 */
@Service
public class ClockServiceImpl implements ClockService {
    @Resource
    private ClockMapper clockMapper;
    @Resource
    private UserService userService;

    @Override
    public PageVO<UserClockVO> pageQuery(PageParam pageParam) {
        Integer uid = UserUtils.getUser();

        try {
            // 1. 构建动态查询条件
            LambdaQueryWrapper<Clock> queryWrapper = Wrappers.lambdaQuery(Clock.class)
                    .eq(Clock::getUid, uid)
                    // 上班打卡时间范围查询
                    .apply(StringUtils.isNotBlank(pageParam.getAmStart()) && StringUtils.isNotBlank(pageParam.getAmEnd()),
                            "am BETWEEN {0} AND {1}",
                            pageParam.getAmStart(), pageParam.getAmEnd())
                    .apply(StringUtils.isNotBlank(pageParam.getAmStart()) && StringUtils.isBlank(pageParam.getAmEnd()),
                            "am >= {0}", pageParam.getAmStart())
                    .apply(StringUtils.isBlank(pageParam.getAmStart()) && StringUtils.isNotBlank(pageParam.getAmEnd()),
                            "am <= {0}", pageParam.getAmEnd())
                    // 下班打卡时间范围查询
                    .apply(StringUtils.isNotBlank(pageParam.getPmStart()) && StringUtils.isNotBlank(pageParam.getPmEnd()),
                            "pm BETWEEN {0} AND {1}",
                            pageParam.getPmStart(), pageParam.getPmEnd())
                    .apply(StringUtils.isNotBlank(pageParam.getPmStart()) && StringUtils.isBlank(pageParam.getPmEnd()),
                            "pm >= {0}", pageParam.getPmStart())
                    .apply(StringUtils.isBlank(pageParam.getPmStart()) && StringUtils.isNotBlank(pageParam.getPmEnd()),
                            "pm <= {0}", pageParam.getPmEnd())
                    .orderByDesc(Clock::getAm);
            Page<Clock> page = new Page<>(pageParam.getPageNum(), pageParam.getPageSize());
            Page<Clock> clockPage = clockMapper.selectPage(page, queryWrapper);  // 按上班时间倒序
            List<Clock> records = clockPage.getRecords();
            Calendar calendar = Calendar.getInstance();
            List<UserClockVO> voList = new ArrayList<>();
            User user = userService.getUserById();
            for (Clock record : records) {
                UserClockVO vo = new UserClockVO();
                vo.setUid(record.getUid());
                vo.setUsername(user.getUsername());
                vo.setAm(record.getAm());
                vo.setPm(record.getPm());
                if (record.getAm() == null || record.getPm() == null) {
                    vo.setStatus("未打卡");
                    voList.add(vo);
                    continue;
                }
                calendar.setTime(record.getAm());
                // 设置标准上班时间（9:00）
                calendar.set(Calendar.HOUR_OF_DAY, 9);
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                Date standardAm = calendar.getTime();

                calendar.setTime(record.getPm());
                // 设置标准下班时间（18:00）
                calendar.set(Calendar.HOUR_OF_DAY, 18);
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                Date standardPm = calendar.getTime();

                // 比较实际打卡时间与标准时间
                boolean amOk = record.getAm().before(standardAm) || record.getAm().equals(standardAm);
                boolean pmOk = record.getPm().after(standardPm) || record.getPm().equals(standardPm);

                if (amOk && pmOk) {
                    vo.setStatus("正常");
                } else if (!amOk && pmOk) {
                    vo.setStatus("迟到");
                } else if (amOk && !pmOk) {
                    vo.setStatus("早退");
                } else if (record.getAm() == null && record.getPm() == null) {
                    vo.setStatus("旷工");
                } else {
                    vo.setStatus("迟到且早退");
                }

                voList.add(vo);
            }
            PageVO<UserClockVO> pageVO = new PageVO<>();
            pageVO.setTotal(clockPage.getTotal());
            pageVO.setDataList(voList);
            return pageVO;


        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String amClock(String am) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Integer uid = UserUtils.getUser();
            Date clockTime = (am == null || am.isEmpty()) ? new Date() : sdf.parse(am);
            // 检查今天是否已打过上班卡
            Date today = getStartOfDay(clockTime);
            Clock existing = clockMapper.selectOne(Wrappers.lambdaQuery(Clock.class)
                    .eq(Clock::getUid, uid)
                    .ge(Clock::getAm, today));

            if (existing != null) {
                return "今日已打过上班卡";
            }

            // 创建新记录
            Clock clock = new Clock();
            clock.setUid(uid);
            clock.setAm(clockTime);
            clockMapper.insert(clock);

            // 判断打卡状态
            return isLate(clockTime) ? "迟到" : "正常";
        } catch (ParseException e) {
            throw new RuntimeException("时间格式错误，请使用yyyy-MM-dd HH:mm:ss格式", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String pmClock(String pm) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Integer uid = UserUtils.getUser();
            Date clockTime = (pm == null || pm.isEmpty()) ? new Date() : sdf.parse(pm);
            Date today = getStartOfDay(clockTime);

            // 查找今天上午的打卡记录
            Clock clock = clockMapper.selectOne(Wrappers.lambdaQuery(Clock.class)
                    .eq(Clock::getUid, uid)
                    .ge(Clock::getAm, today));

            if (clock == null) {
                throw  new CustomerException("500","请先打上班卡") ;
            }

            // 检查是否已打过下班卡
            if (clock.getPm() != null) {
                return "今日已打过下班卡";
            }

            // 更新下午打卡时间
            clock.setPm(clockTime);
            clockMapper.updateById(clock);

            // 判断打卡状态
            return isEarly(clockTime) ? "早退" : "正常";
        } catch (ParseException e) {
            throw new RuntimeException("时间格式错误，请使用yyyy-MM-dd HH:mm:ss格式", e);
        }
    }

    @Override
    public ClockStatsVO getUserClockStats() {
        Integer uid = UserUtils.getUser();
        // 1. 查询用户所有打卡记录
        List<Clock> records = clockMapper.selectList(
                Wrappers.lambdaQuery(Clock.class)
                        .eq(Clock::getUid, uid)
                        .isNotNull(Clock::getAm)
        );

        // 2. 初始化统计结果
        ClockStatsVO stats = new ClockStatsVO();
        stats.setTotalRecords(0);
        stats.setLateRecords(0);
        stats.setEarlyRecords(0);
        stats.setNormalRecords(0);
        stats.setAbnormalRecords(0);
        stats.setTotalRecords(records.size());

        // 3. 遍历记录进行统计
        for (Clock record : records) {
            boolean isLate = isLate(record.getAm());
            boolean isEarly = record.getPm() != null && isEarly(record.getPm());
            // 迟到
            if (isLate) {
                stats.setLateRecords(stats.getLateRecords() + 1);
            }
            // 早退
            if (isEarly) {
                stats.setEarlyRecords(stats.getEarlyRecords() + 1);
            }
            // 正常
            if (!isLate && !isEarly) {
                stats.setNormalRecords(stats.getNormalRecords() + 1);
            }
            // 迟到或早退
            if (isLate || isEarly){
                stats.setAbnormalRecords(stats.getAbnormalRecords() + 1);
            }
        }

        return stats;
    }

    // 辅助方法：获取当天的开始时间（00:00:00）
    private Date getStartOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    // 判断是否迟到（9:00之后）
    private boolean isLate(Date clockTime) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(clockTime);
        cal.set(Calendar.HOUR_OF_DAY, 9);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return clockTime.after(cal.getTime());
    }

    // 判断是否早退（18:00之前）
    private boolean isEarly(Date clockTime) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(clockTime);
        cal.set(Calendar.HOUR_OF_DAY, 18);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return clockTime.before(cal.getTime());
    }


}
